/* 
 * File:   ClustalWSample.cpp
 * Author: loskana
 * 
 * Created on March 7, 2011, 11:52 PM
 */

#include <set>
#include <vector>
#include "ClustalWSample.h"
#include "NewickTree.h"
#include "NewickTreeFactory.h"

namespace Biopool
{

// TODO: passa string con deserializzazione
ClustalWSample::ClustalWSample(NewickTree newickEvolTree, std::vector<std::string> inSequences )
: sequences(inSequences) {
    
    std::cout << "iteraz" << std::endl;
    
    // this->evolTree = NewickTreeFactory::deserialize(newickEvolTree);
    this->evolTree = new NewickTree(newickEvolTree);	
    
	// set distances parameters
	this->alignGapPenalty = 10;
	this->alignGapExtension = 2;
	
	// create Align classes 
    std::ifstream matrixFile("data/blosum62.dat");
	if (!matrixFile) 
        throw "Error opening structure matrix file.";
        
    this->subMatrix = new SubMatrix(matrixFile);
    this->gapFunction = new AGPFunction(this->alignGapPenalty, this->alignGapExtension);    
}

ClustalWSample::ClustalWSample(const ClustalWSample& orig) {
}

ClustalWSample::~ClustalWSample() {
	delete(this->subMatrix);
	delete(this->gapFunction);
}

std::vector<std::string> ClustalWSample::execute() {

    // operazioni iniziali, controllo operandi

    // lancia allineamento ricorsivo
    return this->recursiveMultipleAlignment(this->evolTree->getRoot());
}

std::vector<std::string> ClustalWSample::recursiveMultipleAlignment(NewickTree::Node * evolNode) {

    // se è foglia, ottiene la sequenza che referenzia, e la ritorna
    if (evolNode->isLeaf()) {
        intSet * seqIds = evolNode->getSequencesSet();
        // prendi il primo (e unico)
        int seqId= *(seqIds->upper_bound(0));
        std::vector<std::string> retVector;
        retVector.push_back(this->sequences[seqId]);
        return retVector;
    }

    // lancia ricorsivamente sui figli destri e sinistri
    std::vector<std::string> leftChildAlign = this->recursiveMultipleAlignment(evolNode->getLeftChild());
    std::vector<std::string> rightChildAlign = this->recursiveMultipleAlignment(evolNode->getRightChild());

    // time for magick!
    // this->sequenceData = new SequenceData(2, firstSeq, secondSeq);
    // this->scoringScheme = new ScoringP2P(this->subMatrix, this->sequenceData, 0, 1.00);
    // this->align = new NWAlign(sequenceData, this->gapFunction, this->scoringScheme);

	// this->align->doMatchScore(cout);
	
    // get alignment
    // vector<string> match = this->align->getMatch();     

    // return match;

    // noi siamo pigri, e torniamo i due vettori uniti.
    for (unsigned int i = 0; i < rightChildAlign.size(); i++)
    {
        leftChildAlign.push_back(rightChildAlign[i]);
    }

    return leftChildAlign;
}

} /* namespace */
